function  bci=bciGetParam(bci,varargin)
% bci=bciGetParam(bci,varargin) Sets user defined parameters for brain-computer-interface 
%
% PURPOSE: 
% Central function to define user selectable parameters for a bci run.
% Specifies parameters for recording device, user interface, feature selection, classifier
% training, classifier evaluation. 
% Which parameters are required for which experiment in documented in the
% wiki. 
%
% INPUT:
% bci:      OPTIONAL A bci structure holding the parameters. All fields defined in
%           this function will be overwritten. If nothing was passed, a
%           with fields defined her will be passed. 
% 
% OUTPUT:
% bci:      A bci structure hoding the parameters defined in the script
%
% REQUIREMENTS:
% none
% 
% TODO:
% Documentation of parameters in wiki 

% To blame:
% CR wrote it
% JR 10/11/21 included field to specify recording system
% JR 11/03/04 added defnition of paths 
% CR 11/05/03 included field to specify paradigm
% CR 11/05/10 extended trigger param, revised retrain parameter, added bootstrap parameter

%% Path to BCI software
if ~exist('bciRun','file'),
    basePath='c:\matlab\MD_BCI';
    addpath(basePath);
    bciPaths;
end

%% Define recording system
% valid choices are currently:
% TDT, BTI, Biosemi, BrainAmp, Walter
% ''  %The empty string will assume a default recording system. If you are
% really lucky it may work.  
bci.recordingSystem='BTI';  % TDT, BTI, Biosemi, BrainAmp, Walter
if strcmp(bci.recordingSystem,'TDT'),
    % TDT
    % All channels used for BCI must have the same sampling frequency
    bci.TDT.dataBufferName='motormap'; % TDT: name of the name of recording device in open Workbench (e.g. motormap, Amp, Acq)
    bci.TDT.channels2Read{1}=1:4; %TDT organizes channels in blocks. Channels are specified for each block separately.
    %bci.TDT.channels2Read{2}=1:64;
    bci.TDT.blockNames2Read{1}='ANIN';%'Wav1'; %The name of each block. Names can be found in open developer.
    %bci.TDT.blockNames2Read{1}='Wav2';
    % channel_params
    bci.preprocChan=[1:bci.transmitChan]; %list of channels for preprocessing
    bci.chanOfInterest=bci.preprocChan; %list of channels for classification (subset of preprocChan)
    bci.chanOfInterest = bciFind(bci.preprocChan,bci.chanOfInterest); % Make sure all channels of interest exist.
    bci.chanLocFile = '';%'D:\MD_BCI\capLayout\grid64.lay';% channel locations for topoplot
elseif strcmp(bci.recordingSystem,'BTI'),
    % BTI
    % channel_params
    bci.configFile = 'D:/MD_BCI/MEGconfig/Center120_REF.mat'; %header information for BTI Listener
    bci.preprocChan=[3:122]; %channel for preprocessing
    bci.referenceChan = 120+[1:10,12:23];
    bci.chanOfInterest = bciFind(bci.preprocChan,3:122);%%channel for classification (subset of preprocChan)
    bci.chanLocFile = 'D:/MD_BCI/capLayout/4D248.lay';%'EEG_29_cartesianSorted.lay';
elseif strcmpi(bci.recordingSystem,'Biosemi'),
    % Biosemi
    % channel_params
    bci.preprocChan = [1:22]; %channel take from the datastream for preprocessing
    bci.chanOfInterest = bciFind(1:22,bci.preprocChan);%%channel for classification (subset of preprocChan)
    bci.chanLocFile = 'E:\MD_BCI\capLayout\biosemi64.lay'; %layout file (in MD_BCI package)
    bci.configFile='';
elseif strcmpi(bci.recordingSystem,'BrainAmp'),
    % BrainAmp
    % channel_params
    bci.preprocChan=1:64; %channel for preprocessing
    bci.chanOfInterest = bciFind(bci.preprocChan,1:64);%%channel for classification (subset of preprocChan)
    bci.chanLocFile = 'E:\MD_BCI\capLayout\brainAmp64.lay';
elseif strcmpi(bci.recordingSystem,'Walter'),
    % Walter
    bci.configFile='';
    % channel_params
    bci.param.trigChan=72; % Channel where trigger are encoded
    bci.preprocChan=1:64; %channel for preprocessing
    bci.chanOfInterest = bciFind(bci.preprocChan,1:bci.transmitChan);%%channel for classification (subset of preprocChan)
    bci.chanLocFile = '';
elseif strcmpi(bci.recordingSystem,'ECOGtest'),
    % Test Scenario: 1st electrode excluded, channel 10 bad, channel 11
    % zero (using bciCalib), 6 and 7 are most informative
    % (using bciCheckFeatures)
    bci.configFile='';
    % channel_params
    bad_chan=[10,11];
    bci.preprocChan=1:64;%setdiff(2:64,bad_chan); %channel for preprocessing
    bci.chanOfInterest = [1:64];%bci.preprocChan;%%channel for classification (subset of preprocChan)
    bci.chanLocFile = 'E:/MD_BCI/capLayout/INIcolumnArray64.grid';
end
    
bci.dataBufferName='buffer://localhost:1972'; % name of a TCP/IP stream read by a fieldtrip function

%% Define paradigm
% valid choices are currently:
% 1 - cursor task; 2 - continuous Arm control; 
% 3 - actuated grasp of arm
% 4 - actuated grasp of arm, one target only (use class base and left or right)
% 11 - SSVEP 
% 12 - P300
% 13 - SSVEP + grasp control
% 14 - P300 + grasp control
bci.paradigm.id = 14;
% stimulation params
if bci.paradigm.id >2,
    bci.stimulation.targetColor = [0 1 0, 1 0 0]; %color of target, 2nd triplet for base
    bci.stimulation.armSystem = 'left'; % arm to show 'right' or 'left'
    bci.paradigm.fbTrialTimeOut = 15;
    bci.paradigm.fbPredictionWindow = 4; % length of window [s] to get local true positives rate
    bci.paradigm.fbPredRate = 0.7; % threshold of minimum local prediction rate in time window    
    bci.paradigm.fbVelocityToDestination = 5; % velocity of arm (10/x sec) recommended:2
    bci.paradigm.stimVelocityToDestination = 5; % move Arm after train trial? set 0 for no movement, 2 for double velocity (recommended)
end
if bci.paradigm.id >0 && bci.paradigm.id<3,
    bci.paradigm.fbTrialTimeOut = 60;
end
bci.paradigm.fbBreakDur = 3; % minimum of seconds between feedback trials
bci.paradigm.fbSuccessDur = 1.5; % seconds to hold final position
bci.paradigm.fbClassifierTrialLength = 4; % trial length of feedback data to retrain the classifier; 0 for no retraining
bci.paradigm.fbSoundFile = '';
% flicker paradigm params
bci.paradigm.flickerFreqs = [60/9 60/7 10 15 ]; % flicker Frequencies
bci.paradigm.flickerAlignment = [2 1 3 4]; % which frequency at which position
if bci.paradigm.id>10,
    bci.paradigm.stimVelocityToDestination= 0;
end
% P300 paradigm params
bci.paradigm.doAverageFlashEvents = ~true;
bci.paradigm.nTargetFlashes = 5;
bci.paradigm.flashWin = 0.8; % length of window to extract P300
bci.paradigm.flashSyncTrigger = 64;
bci.paradigm.objectAlignment = 'x'; % x diagonal, + horizontal/vertical, - robot scenario

% experimental train params
bci.numTrials = 4; % 15 see bciGenerateEvents for generating event vector
bci.movDur=[10]; % 
bci.fixDur=2;
bci.preRunDur = 0; % duration to wait
bci.eventStr = {}; % outputs linked to event ID%no more used
bci.baseEvent=[]; % event ID for rest
bci.leftEvent=[]; % event ID for left movement
bci.rightEvent=[]; % event ID for right movement
bci.eventsToClassify = [ 1 2 3 4 5 6]; 

bci.RT = 0.0; % assumed reaction time of subject

% experimental test params
bci.testRunDur=120; % duration of feedback run in sec
bci.cursor = 'O'; %no more used
bci.target = '+'; %no more used
bci.predictionRate = 2; %refresh rate for prediction (movement change) in Hz
bci.cursorRate = 5; %refresh rate for cursor movement in Hz
bci.cursorSpeed = 0.1; % in percent of screen width per second
bci.minDist = 0.1; % minimum distance target to cursor for new trial (>0; <0.5)

% preprocessing params
bci.param.bandFreqs = [1.0 12];%[0.5 200]; bandpass frequencies (lowpass if scalar value), no filter if empty
bci.param.resampFreq = [32];
bci.param.baselineLength = 10.0; % length of baseline in sec (from sliding window beginning)

% ARTIFACT detection params
bci.param.artifactThresh = 3.5e-12;%check this!!! % threshold for discarding artifact epochs (in measurement unit)
bci.param.badChanThresh = 0.2;  % ratio of artifact epochs to exclude whole channels

% classification params
bci.param.winsize = 10.0;%0.5; % width of window for classification in s
bci.param.winoffset = 0.0; %0.25; % offset before and after window (for preprocessing)
bci.param.winsrate = 0.1; % sampling rate for window in Hz (5Hz=0.2s shift size)

%% --------------------- FREQUENCIES /TAPERS 
bci.param.freq=[1];%[6 8 10 13 17 20 25 30];%frequency bins for spectrograms;
bci.param.tapers = [2 3]; %[time-bandwidth-product nTapers]
%% -------------------------

% bci.param.spectrogramFreq = 2; % rate of spectrogram estimations [Hz]
% (prepared for temporal frequency space)
bci.param.classifier = 'svm'; %classifier, currently: 'svm' (2class),'logreg'(3class),'svmmulti'(3class)
bci.param.baseC = []; % svm regularization parameter, if empty, see getDefC.m
bci.param.movdirC = []; % svm regularization parameter 
bci.param.specMethod = 0; % 0=timediscrete 1= fft; 2=taper; 3= AR model, 4=exact fft
bci.param.fftWin='hamming'; % type 'help window' for more windows (e.g.hamming,hann,tukeywin,...), only for fft
bci.param.fftSmooth = false; % smooth frequency bins
bci.param.ARorder = 3;       % AR model order (if specMethod = 3)
bci.param.balanceTrainSet=~true; % use equal class sizes
bci.param.bootstrapSize = 0; % number of maximum samples after bootstrap, 0 if no bootstrap
bci.param.maxTrainSamp = 300; %maximum number of train data per class
bci.param.retrainClassifier = ~true; % trial lenth of feedback data to retrain the classifier; 0 for no retraining

% spatial filtering
bci.param.spatialMethod='laplace'; %spatial filter method 'laplace' or 'gauss' (i.e. edge filter or smoothing)
bci.param.spatialFilter=0; % 0:no spatial filter 
                           % 1:Biosemi Cap 64 elec.
                           % 2:Easycap 29elec.
                           % 3:BrainAmp 64elec cap
                           % 4:BTI 248chan MEG
                           % 5&6: Walter 64 & 32 elec
                           % 7: e.g. Ecog grid 64 electrodes, not yet
                           % implemented
bci.param.chanDistThresh=[];    % channel distance thresh for laplace coeff estimation in radians;
                                % equals FWHM for gauss kernel 
                                % if empty see bciSpatialFilterCoeffs for
                                % default values

bci.param.CSPfilter = 0; % number of CSP filter, zero if no CSP 
                         % important: when using CSP, specMethod must be
                         % 0!!!
bci.param.CSPbandFreqs=[5 20;10 30;20 40]; % bandpass frequencies for CSP, multiple bands possible (define nx2 matrix)

bci.param.detrend=false; %true;  % detrending

bci.param.doNormalizeFeat = true; %normalize feature vector
bci.param.featureSelection = {}; % feature reduction method, empty for no feature selection. 
                                       % 'rsqu','tval','svm',followed by 'chan','freq', 'band','raw',
                                       % followed by number or fraction of features
                                       % eg: 'tvalchan32' (best 32 chans),'svmfreq0.1' 10% of svm weights
                                       % successive featureselections
                                       % possible (use cell array of
                                       % strings)

bci.refChanCAR = []; % channels to get common average reference if empty, no CAR will be removed

% artifact correction
bci.param.artifactSourceChan=[]; % for eeg eye movement correction; not yet tested

% trigger params
bci.param.doSendTrigger = true; % true if send trigger
bci.param.doReceiveTrigger = true; % true if receive trigger for synchronization
bci.param.roundtripLatency = 0.2; %assumed delay if doReceiveTrigger is disabled
bci.param.trigAddress = hex2dec('378'); % parallel port address (empty for using DIO)
bci.param.trigDur = 0.008; % trigger duration in s
bci.param.sendStateTrigger=true; % send state trigger at each classification 

% save params
bci.param.saveRawDat=true; % keep raw data if you want to recreate epochs
bci.param.saveEpochs=true; % keep epochs if you want to reload it as created online
